package corewarsxxi.logic;

import java.io.Serializable;

/**
 * MemoryCell contains a opCode and two MemoryFields - A and B.
 *
 * @version 1.0
 * @see     corewarsxxi.logic.OpCode
 * @see     corewarsxxi.logic.MemoryField
 * @see     corewarsxxi.logic.Cloneable
 * @author  Luís Fonseca, ei10139 @ FEUP
 */
public class MemoryCell implements Cloneable, Serializable
{
    /** The OpCode*/
    protected OpCode opCode;

    /** The A-Field MemoryField*/
    protected MemoryField aField;

    /** The B-Field MemoryField*/
    protected MemoryField bField;

    /**
     *
     * @param opCode
     * @param aField
     * @param bField
     */
    public MemoryCell(OpCode opCode, MemoryField aField, MemoryField bField)
    {
        this.opCode = opCode;
        this.aField = aField;
        this.bField = bField;
    }
    
    @Override
    public String toString()
    {
        return "" + this.opCode.getClass().getSimpleName() + "   " + aField + ", " + bField + "";
    }

    /**
     *
     * @param opCode
     */
    public void changeOpCode(OpCode opCode)
    {
        this.opCode = opCode;
        Core.getInstance().memArray.notifyObs(this);
    }

    @Override
    public Object clone()
    {
        return new MemoryCell(opCode, (MemoryField)aField.clone(), (MemoryField)bField.clone());
    }

    /**
     * @return the aField
     */
    public MemoryField getaField() {
        return aField;
    }

    /**
     * @param aField the aField to set
     */
    public void setaField(MemoryField aField) {
        this.aField = aField;
        Core.getInstance().memArray.notifyObs(this);
    }

    /**
     * @return the bField
     */
    public MemoryField getbField() {
        return bField;
    }

    /**
     * @param bField the bField to set
     */
    public void setbField(MemoryField bField) {
        this.bField = bField;
        Core.getInstance().memArray.notifyObs(this);
    }

    /**
     * @return the opCode
     */
    public OpCode getOpCode() {
        return opCode;
    }

    /**
     *
     * @param value
     * @param aMode
     * @param aField
     */
    public void setStoredaFieldValue(int value, AddressingMode aMode, boolean aField)
    {
        this.aField.setStoredValue(value);
        this.aField.changeAddressingMode(aMode, aField);
        Core.getInstance().memArray.notifyObs(this);
    }

    /**
     *
     * @param value
     */
    public void setStoredaFieldValue(int value)
    {
        this.aField.setStoredValue(value);
        Core.getInstance().memArray.notifyObs(this);
    }

    /**
     *
     * @param value
     * @param aMode
     * @param aField
     */
    public void setStoredbFieldValue(int value, AddressingMode aMode, boolean aField)
    {
        this.bField.setStoredValue(value);
        this.bField.changeAddressingMode(aMode, aField);
        Core.getInstance().memArray.notifyObs(this);
    }

    /**
     *
     * @param value
     */
    public void setStoredbFieldValue(int value)
    {
        this.bField.setStoredValue(value);
        Core.getInstance().memArray.notifyObs(this);
    }

    /**
     *
     * @return
     */
    public int preDecbFieldValue()
    {
        Core.getInstance().memArray.notifyObs(this);
        return this.bField.preDecValue();
    }
}